Skip to content

Hacker News - Dynamic Dark by calebj0seph

Screenshot of Hacker News - Dynamic Dark

Details

Authorcalebj0seph

LicenseNo License

Categoryycombinator

Created

Updated

Size9.3 kB

Statistics

Learn how we calculate statistics in the FAQ.

Failed to fetch stats.

Description

Classic Hacker News design with automatic or configurable light/dark mode. Includes some spacing and typography tweaks to improve legibility.

Notes

This userstyle can be configured. See the cog icon in Stylus labelled 'Configure' (not to be confused with the pencil icon to edit).

You can configure:

  • Dark/light mode
    • Automatically switch between dark and light mode depending on your system preferences (default)
    • Use only either dark or light mode, ignoring your system preferences
  • The maximum width of the page (disabled by default)
    • You can use any valid CSS value
    • I'd suggest trying 1000px as a good balance between readability and space


I've put in a lot of effort to make sure every minor detail of Hacker News looks good in dark mode, including edge cases like the colors at Christmas time. Please leave a review if you run into anything I missed!

Source code

/* ==UserStyle==
@name         Hacker News - Dynamic Dark
@version      20230720.12.53
@namespace    userstyles.world/user/calebj0seph
@description  Classic Hacker News design with automatic light/dark mode. Includes some minor spacing and typography tweaks to improve legibility.
@author       calebj0seph
@license      No License
@preprocessor stylus
@var          select themeOverride "Theme override"                                     ["None*", "Light", "Dark"]
@var          text   maxWidth      "Max page width (e.g. 800px, use 'none' to disable)" "none"
==/UserStyle== */
@-moz-document domain("news.ycombinator.com") {
  input-color = #000000;
  input-color-dark = #fbfbfb;
  input-background = #f9f9f9;
  input-background-dark = #2f2f2f;
  input-border = #d3d3d3;
  input-border-dark = #4d4d4d;
  font-list = 'Segoe UI Variable Small', 'Segoe UI', 'Helvetica Neue', sans-serif;

  dark-accepted-color-schemes = (dark);

  if themeOverride == 'Light' {
    pop(dark-accepted-color-schemes);
  } else if themeOverride == 'Dark' {
    push(dark-accepted-color-schemes, light);
  }

  darkMode() {
    for scheme in dark-accepted-color-schemes {
      @media (prefers-color-scheme: scheme) {
        {block}
      }
    }
  }

  button(scale-factor) {
    &,
    &:link,
    &:visited {
      display: inline-block;
      padding: 0.25em 0.5em;
      font-family: font-list !important;
      font-size: 0.85rem * scale-factor !important;
      font-weight: 500;
      text-decoration: none;
      border: 1px solid input-border;
      border-radius: 3px;
      background: input-background;
      color: input-color!important;
      cursor: default;
      transition: background 0.05s;

      +darkMode() {
        border: 1px solid input-border-dark;
        background: input-background-dark;
        color: input-color-dark!important;
      }
    }

    &:hover {
      background: darken(input-background, 5%);

      +darkMode() {
        background: lighten(input-background-dark, 5%);
      }
    }

    &:active {
      background: darken(input-background, 10%);

      +darkMode() {
        background: lighten(input-background-dark, 15%);
      }
    }
  }

  body,
  .pagetop,
  .yclinks {
    font-family: font-list;
  }

  .pagetop {
    color: rgba(#000000, 0.45);
  }

  .pagetop a:link,
  .pagetop a:visited {
    color: rgba(#000000, 0.7);
  }

  .pagetop > b:first-child,
  .pagetop > b:first-child a {
    color: #000000;
  }

  .pagetop .topsel a:link,
  .pagetop .topsel a:visited,
  .pagetop font[color="#ffffff"] {
    color: #000000;
    font-weight: bold;
  }

  #hnmain,
  table[bgcolor="#f6f6ef"] {
    max-width: maxWidth;
    border-radius: 3px;
  }

  #hnmain > tbody > tr:first-child > td:first-child,
  table[bgcolor="#f6f6ef"] > tbody > tr:first-child > td:first-child {
    border-top-left-radius: 3px;
    border-top-right-radius: 3px;
  }

  #hnmain > tbody > tr:last-child > td:last-child,
  table[bgcolor="#f6f6ef"] > tbody > tr:last-child > td:last-child {
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
  }

  #hnmain > tbody > tr > td[bgcolor="#ff6600"]:first-child > table,
  table[bgcolor="#f6f6ef"] > tbody > tr > td[bgcolor="#ff6600"] > table {
    padding: 5px 10px !important;
  }

  .pagetop > b:first-child {
    margin: 0px 8px 0px 3px;
  }

  // Add spacing to columns on left of page
  .athing:not(.comtr) td:first-child,
  #pagespace[title="Lists"] + tr > td:first-child,
  #pagespace[title="Add Comment"] + tr + tr > td:first-child,
  #pagespace[title="Edit"] + tr > td:first-child,
  #pagespace[title="Submit"] + tr + tr > td:first-child,
  #pagespace[title^="Profile:"] + tr > td:first-child,
  #pagespace[title^="Reset Password"] + tr + tr > td:first-child {
    padding-left: 14px;

    & td:first-child {
      padding-left: 0;
    }
  }

  // Left spacing for comment threads
  .athing.comtr td:first-child {
    padding-left: 4px!important;

    & td:first-child {
      padding-left: 0;
    }
  }

  // Left spacing when viewing a submission
  #pagespace:not([title="Add Comment"]):not([title="Edit"]) ~ tr table.fatitem tr td:first-child {
    padding-left: 10px!important;
    
    & td:first-child {
      padding-left: 0;
    }
  }

  // Left padding for upvoted comments page
  #pagespace[title="Upvoted comments"] + tr td:first-child {
    padding-left: 16px;

    & td:first-child {
      padding-left: 0;
    }
  }

  // Hide invisible vote arrow column on the upvoted comments page
  #pagespace[title="Upvoted comments"] + tr td.votelinks {
    display: none;
  }

  // Fix left spacing on jobs page
  .athing > td > img[src="s.gif"] {
    width: 0;
  }

  // Adjust left margin for sub-navigation on past and favoriutes pages
  div[style^="margin-left:36px;"] {
    margin-left: 26px!important;
  }

  tr > td[bgcolor="#ffffaa"]:first-child {
    padding: 0 5px!important;
  }

  // Add spacing to right of page in some places
  .athing td:last-child,
  tr td.subtext:last-child,
  .toptext,
  #pagespace[title^="Profile:"] + tr > td:last-child {
    padding-right: 16px;

    & td:last-child {
      padding-right: 0;
    }
  }

  .title:first-child .rank:not(:empty) {
    display: inline-block;
    min-width: 24px;
    padding-right: 4px;
    font-family: font-list;
    font-size: 0.95rem;
  }

  .title:last-child {
    font-family: font-list;
    font-size: 0.95rem;
    font-weight: 500;
    padding-bottom: 0.05rem;
  }

  .title .morelink {
    font-size: 0.9rem;
  }

  a:link {
    color: #323232;
  }

  .comhead,
  .subtext {
    font-family: font-list;
    font-size: 0.8rem;
    font-weight: normal;
  }

  .toptext,
  .comment {
    font-family: font-list;
    font-size: 0.85rem;
    font-weight: normal;
  }

  td {
    font-family: font-list;
    font-size: 0.8rem;
  }

  .itemlist {
    padding-left: 0.8rem;
  }

  .votelinks {
    padding-right: 0.35rem;
  }

  .votearrow {
    margin-top: 5px;
    background: no-repeat center/10px url('triangle.svg');
  }

  input[type="submit"], a[href="forgot"] {
    button(1.0);
  }

  .reply a {
    button(0.8);
  }

  tr.spacer {
    height: 0.4rem !important;
  }

  .yclinks {
    font-size: 0.7rem;
  }

  // Christmas colors
  td[bgcolor="#cc1010"] .pagetop {
    color: rgba(255, 255, 255, 0.7);
  }

  td[bgcolor="#cc1010"] .pagetop a:link,
  td[bgcolor="#cc1010"] .pagetop a:visited {
    color: #fbfbfb;
  }

  td[bgcolor="#cc1010"] .pagetop > b:first-child {
    color: #fbfbfb;
  }

  td[bgcolor="#cc1010"] .pagetop .topsel a:link,
  td[bgcolor="#cc1010"] .pagetop .topsel a:visited,
  td[bgcolor="#cc1010"] .pagetop font[color="#ffffff"] {
    color: #000000;
  }

  td[bgcolor="#cc1010"] .pagetop > b:first-child a {
    color: #fbfbfb !important;
  }

  td[bgcolor="#cc1010"] .pagetop a:visited {
    color: #fbfbfb;
  }

  +darkMode() {
    body {
      background: #020202;
    }

    #hnmain,
    [bgcolor="#fafaf0"],
    [bgcolor="#f6f6ef"] {
      background: #20201c;
    }
    
    // Mourning
    [bgcolor="#000000"] {
      background: #727272;
    }

    #hnmain > tbody > tr > td[bgcolor="#ff6600"]:first-child,
    table[bgcolor="#f6f6ef"] > tbody > tr > td[bgcolor="#ff6600"]:first-child {
      background: #f05900;
    }

    textarea,
    input[type="text"],
    input[type="url"],
    input[type="password"] {
      border: 1px solid input-border-dark;
      background: input-background-dark;
      color: input-color-dark;
    }

    .pagetop {
      color: rgba(#fbfbfb, 0.6);
    }

    .pagetop a:link,
    .pagetop a:visited {
      color: rgba(#fbfbfb, 0.85);
    }

    .pagetop > b:first-child,
    .pagetop > b:first-child a {
      color: #fbfbfb;
    }

    .pagetop .topsel a:link,
    .pagetop .topsel a:visited,
    .pagetop font[color="#ffffff"] {
      color: #fbfbfb;
    }

    font[color="#3c963c"] {
      color: #6ac366;
    }

    td[bgcolor="#ffffaa"] td,
    #me,
    [bgcolor="#fafaf0"] {
      color: rgba(#fbfbfb, 0.8) !important;
    }

    body,
    .title,
    td,
    .admin td,
    .hnmore a:link,
    a:visited {
      color: #ababab;
    }

    a:link {
      color: #fbfbfb;
    }

    .subtext,
    .subtext a:link,
    .subtext a:visited,
    .comhead,
    .comhead a:link,
    .comhead a:visited,
    [bgcolor="#fafaf0"] b {
      color: #b9b9b9;
    }

    .c00,
    .c00 a:link {
      color: #fbfbfb;
    }

    .c5a,
    .c5a a:link,
    .c5a a:visited {
      color: #e5e5e5;
    }

    .c73,
    .c73 a:link,
    .c73 a:visited {
      color: #cfcfcf;
    }

    .c82,
    .c82 a:link,
    .c82 a:visited {
      color: #b9b9b9;
    }

    .c88,
    .c88 a:link,
    .c88 a:visited {
      color: #a3a3a3;
    }

    .c9c,
    .c9c a:link,
    .c9c a:visited {
      color: #8e8e8e;
    }

    .cae,
    .cae a:link,
    .cae a:visited {
      color: #797979;
    }

    .cbe,
    .cbe a:link,
    .cbe a:visited {
      color: #666666;
    }

    .cce,
    .cce a:link,
    .cce a:visited {
      color: #525252;
    }

    .cdd,
    .cdd a:link,
    .cdd a:visited {
      color: #404040;
    }

    td[bgcolor="#ffffaa"] {
      background: #977435;
    }

    // Christmas colors
    td[bgcolor="#cc1010"] {
      background: #cc1010 !important;
    }

    [color="#005a00"] {
      color: #2ea658;
    }

    [color="#be2828"] {
      color: #f25d50;
    }
  }
}

Reviews

No reviews yet.